#include <iostream>
#include "graphtypes.h"
#include "GraphOrientedMatrix.h"
#include "GraphOrientedWeightedMatrix.h"
#include "GraphFlowMatrix.h"
#include "GraphFlowList.h"
#include <vector>
#include "unistd.h"
#include "stdlib.h"
#include "string.h"
#include <fstream>
#define NBR_ALGO 4
#define NBR_EXEC_DEF 100
#define CAPMIN_DEF 1
#define CAPMAX_DEF 50
#define MINN_DEF 2
#define PAS_DEF 10
#define NOLIMIT_DEF false;
#define FORCE_LIST_DEF false;;



using namespace std;
/*
  Programme de test principal.
  Ce programme permet de calculer la complexité en temps des algorithmes suivants : 
  - Edmonds-Karp
  - Dinic
  - Ford-Fulkerson
  - Capacity scaling

  Le paramètre obligatoire est :
  - 'n' : Le nombre de sommets du graphe étudié (min. 2). Sa valeur est entrée par l'utilisateur.

  Les paramètres qui peuvent être utilisés :
  - "-cmin X"      : Capacité minimale des graphes créés (1 par défaut)
  - "-cmax X"      : Capacité maximale des graphes créés (50 par défaut)
  - "-cap X Y"     : Capacités minimale et maximales des graphes créés (1 et 50 par défaut)
  - "-nmin X"      : Nombre de sommets minimum (2 par défaut)
  - "-nolimit"     : N'indique pas de valeur maximale au nombre de sommets. Le programme continuera son exécution jusqu'à l'arrêt manuel par l'utilisateur
  - "-nbexe X"     : Nombre de fois qu'une valeur du nombre de sommets sera exécutée. Un nbexe élévé apporte une plus grande précision mais augmente le temps d'exécution (100 par défaut)
  - "-pas X"       : Pas entre deux valeurs du nombre de sommets. Un pas plus petit augmente la précision mais augmente aussi le temps d'exécution (10 par défaut).
  - "-force matrix : Force la structure de données des graphes en matrice
  - "-force list   : Force la structure de données des graphes en listes d'adjacences
  - "--dinic"      : Appel spécifiquement un algorithme. Valable pour : Edmonds-Karp, Dinic, Ford-Fulkerson et Capacity-scaling. Tous présents par défaut.

  Le mécanisme de passage en paramètre est le suivant : 
 - Si le nombre de sommets est passé après "--NomAlgorithme" alors il ne s'applique qu'à ce dernier
 - Si le nombre de sommets est passé avant un "--NomAlgorithme" alors il s'applique à chaque algorithme décrit après (tous par défaut). Néanmoins si une valeur est spéiciquement donnée à un algorithme elle écrasera la valeur globale
 - Les paramètres facultatifs, autre que le choix d'un algorithme particulier, sont forcément en début de commande et sont appliqués à tous les algorithmes

  Les paliers de densité sont : 
  - Densité minium = n-1 arêtes
  - 25% de la densité maximum = (0.25 x (n²-n))/2
  - 50% de la densité maximum = (0.5 x (n²-n))/2
  - 75% de la densité maximum = (0.75 x (n²-n))/2
  - Densité maximum = (n²-n)/2

  Pour appeler les tests sur  tous les algorithmes implémentés : 
  ./benchmark [NOMBRE DE SOMMETS MAX] -[1er Paramètre facultatif] [valeur] -[2e Paramètre facultatif] [valeur] ...


  Pour appeler un ou plusieurs algorithmes spécifiques :
  -Avec les mêmes caractéristiques :
  ./benchmark [NOMBRE DE SOMMETS MAX]  -[1er Paramètre facultatif] [valeur] -[2e Paramètre facultatif] [valeur] --[NOM ALGO 1] --[NOM ALGO 2] ...

  -Avec des caractéristiques différentes : 
  ./benchmark  -[1er Paramètre facultatif] [valeur] -[2e Paramètre facultatif] [valeur]  --[NOM ALGO 1] [NOMBRE DE SOMMETS MAX] --[NOM ALGO 2] [NOMBRE DE SOMMETS MAX]...

*/

/*
  Retourne la chaîne de caractère correspondant à la fonction usage du programme
*/
string usage(char * name){
  string s = "\n\nProgramme principal.\n NAME\n\t";
  s+=name;
  s+=" - test de la complexité de différents algorithmes\n\nSYNOPSIS\n\t>make all\n\n\t>[./]";
  s+=name;
  s+="\n\nAlgorithmes testés :\n\t- Edmonds-Karp\n\t- Dinic\n\t- Ford-Fulkerson\n\t- Capacity scaling\n\nLe paramètre obligatoire est :\n\t- 'n' : Le nombre de sommets du graphe étudié (min. 2). Sa valeur est entrée par l'utilisateur.\n\nLes paramètres qui peuvent être utilisés :\n\t- \"-cmin X\"  : Capacité minimale des graphes créés (1 par défaut)\n\t- \"-cmax X\"  : Capacité maximale des graphes créés (50 par défaut)\n\t- \"-cap X Y\" : Capacités minimale et maximales des graphes créés (1 et 50 par défaut)\n\t- \"-nmin X\"  : Nombre de sommets minimum (2 par défaut)\n\t- \"-nolimit\" : N'indique pas de valeur maximale au nombre de sommets. Le programme continuera son exécution jusqu'à l'arrêt manuel par l'utilisateur\n\t- \"-nbexe X\" : Nombre de fois qu'une valeur du nombre de sommets sera exécutée. Un nbexe élévé apporte une plus grande précision mais augmente le temps d'exécution (100 par défaut)\n\t- \"-pas X\"   : Pas entre deux valeurs du nombre de sommets. Un pas plus petit augmente la précision mais augmente aussi le temps d'exécution (10 par défaut).\n\t- \"-force matrix\" : Force la structure de données des graphes en matrice.\n\t- \"-force list\" : Force la structure de données des graphes en listes d'adjacences.\n\t- \"--dinic\"   : Appel spécifiquement un algorithme. Valable pour : Edmonds-Karp, Dinic, Ford-Fulkerson et Capacity-scaling. Tous présents par défaut.\n\n  Le mécanisme de passage en paramètre est le suivant :\n\t- Si le nombre de sommets est passé après \"--NomAlgorithme\" alors il ne s'applique qu'à ce dernier\n\t- Si le nombre de sommets est passé avant un \"--NomAlgorithme\" alors il s'applique à chaque algorithme décrit après (tous par défaut). Néanmoins si une valeur est spéiciquement donnée à un algorithme elle écrasera la valeur globale\n\t- Les paramètres facultatifs, autre que le choix d'un algorithme particulier, sont forcément en début de commande et sont appliqués à tous les algorithmes\n\nLes paliers de densité sont :\n\t- Densité minium = n-1 arêtes\n\t- 25% de la densité maximum = (0.25 x (n²-n))/2\n\t- 50% de la densité maximum = (0.5 x (n²-n))/2\n\t- 75% de la densité maximum = (0.75 x (n²-n))/2\n\t- Densité maximum = (n²-n)/2\n\nPour appeler les tests sur  tous les algorithmes implémentés : \n\t./main [NOMBRE DE SOMMETS MAX]  -[1er Paramètre facultatif] [valeur] -[2e Paramètre facultatif] [valeur]\n\nPour appeler un ou plusieurs algorithmes spécifiques :\n\t-Avec les mêmes caractéristiques :\n\t\t./main [NOMBRE DE SOMMETS MAX]  -[1er Paramètre facultatif] [valeur] -[2e Paramètre facultatif] [valeur] --[NOM ALGO 1] --[NOM ALGO 2]...\n\t-Avec des caractéristiques différentes : \n\t\t./main  -[1er Paramètre facultatif] [valeur] -[2e Paramètre facultatif] [valeur] --[NOM ALGO 1] [NOMBRE DE SOMMETS MAX] --[NOM ALGO 2] [NOMBRE DE SOMMETS MAX]...";
  return s;
}

/*
  Retourne la chaîne de caractère listant les algorithmes implémentés
*/
string description(){
  return "\n\nListe des algorithmes implémentés :\n\t-Edmonds-Karp : DESCRIPTION\n\t-Dinic : DESCRIPTION\n\t-Ford-Fulkerson : DESCRIPTION\n\t-Capacity-scaling : DESCRIPTION";
}


/*
  TODO : transforme les majuscules ([A-Z]) de arg en miniscule ([a-z]). Ne touche pas aux caractères spéciaux
*/
char* toLowerCase(char arg[]){
  int size = sizeof(arg)/sizeof(char);
  char tmp;
  int i = 0;
  while(i < size){
    tmp = tolower(arg[i]);
    arg[i] = tmp;
    ++i;
  }
  return arg;
}


/*
  Retourne un code en fonction de la chaîne passée en paramètre :
  0 : edmonds-karp / 1 : dinic / 2 : ford-fulkerson / 3 : capacity-scaling
  4 : cmin / 5 : cmax / 6 : cap / 7 : nmin / 8 : nolimit / 9 : nbexe / 10 : pas
  11 : la valeur 0 / 12 : une valeur numérique
  13 : help
  14 : force / 15 : matrix / 16 : list
  -1 : erreur de parsage
*/
int codeArg(char* arg){
  int i = -1;
  if((string)arg == "--edmonds-karp"){
    i = 0;
  }
  if((string)arg == "--dinic"){
    i = 1;
  }
  if((string)arg == "--ford-fulkerson"){
    i = 2;
  }
  if((string)arg == "--capacity-scaling"){
    i = 3;
  }
  if((string)arg == "-cmin"){
    i = 4;
  }
  if((string)arg == "-cmax"){
    i = 5;
  }
  if((string)arg == "-cap"){
    i = 6;
  }
  if((string)arg == "-nmin"){
    i = 7;
  }
  if((string)arg == "-nolimit"){
    i = 8;
  }
  if((string)arg == "-nbexe"){
    i = 9;
  }
  if((string)arg == "-pas"){
    i = 10;
  }
  if((string)arg == "0"){
    i = 11;
  }
  if(atoi(arg) > 0){
    i = 12;
  }
  if((string)arg == "--help"){
    i = 13;
  }
  if((string)arg == "-forcelist"){
    i = 14;
  }
  return i;
}

void parseArguments(char* argv[],bool flags[], summit_t summit_nbrs[], int argc, int* nbexe, int* capMin, int* capMax, int* minN, int* pas, bool* nolimit, bool* forcelist){
  summit_t n;
  int i = 1;
  int code;
  while(i < argc){
    code =  codeArg(toLowerCase(argv[i]));
    switch(code){
    case(-1) : {
      cerr<<"Erreur de parsage de l'argument : "<<argv[i]<<endl;
      exit(100);
    }
    case(0): { //chaine : --edmonds-karp
      flags[0] = true;
      ++i;
      if(i < argc){
	code = codeArg(toLowerCase(argv[i]));
	if(code == 12){
	summit_nbrs[0] = atoi(argv[i]);
	}
	else if(code == -1){
	  cerr<<"Erreur de parsage dans la valeur associé à Edmonds-Karp, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
	else{
	  --i; //Finalement c'était surement un autre argument : il faut le re-parse
	}
      }
      break;
    }
    case(1):{ // --dinic
      flags[1] = true;
      ++i;
      if(i < argc){
	code = codeArg(toLowerCase(argv[i]));
	if(code == 12){
	  summit_nbrs[1] = atoi(argv[i]);
	}
	else if(code == -1){
	  cerr<<"Erreur de parsage dans la valeur associé à Dinic, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
	else{
	  --i; //Finalement c'était surement un autre argument : il faut le re-parse
	}
      }
      break;
    }
    case(2):{ // --ford-fulkerson
      flags[2] = true;     
      ++i;
      if(i <argc){
	if(codeArg(toLowerCase(argv[i])) == 12){
	  summit_nbrs[2] = atoi(argv[i]);
	}
	else if(code == -1){
	  cerr<<"Erreur de parsage dans la valeur associé à Ford-Fulkerson, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
	else{
	  --i; //Finalement c'était surement un autre argument : il faut le re-parse
	}
      }
      break;
    }
    case(3):{
      flags[3] = true;
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if(code == 12){
	  summit_nbrs[3] = atoi(argv[i]);
	}
	else if(code == -1){
	  cerr<<"Erreur de parsage dans la valeur associé à Capacity-scaling, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
	else{
	  --i; //Finalement c'était surement un autre argument : il faut le re-parse
	}
      }
      break;
    }
    case(4):{ //cmin
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if( (code == 12) || (code == 13)){
	  *capMin = atoi(argv[i]);
	}
	else if(code == -1){
	  cerr<<"Erreur de parsage dans la valeur associé à la capacité minimale, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
      }
      break;
    }
    case(5):{ //cmax
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if( (code == 12) || (code == 13)){
	  *capMax = atoi(argv[i]);
	}
	else{
	  cerr<<"Erreur de parsage dans la valeur associé à la capacité maximale, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
      }
      break;
    }
    case(6):{//cap 
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if( (code == 12) || (code == 13)){
	  *capMin = atoi(argv[i]);
	  ++i;
	  if(i <argc){
	    code = codeArg(toLowerCase(argv[i]));
	    if( (code == 12) || (code == 13)){
	      *capMax = atoi(argv[i]);
	    }
	    else{
	      cerr<<"Erreur de parsage dans la valeur associé à la capacité maximale, valeur reçue : "<<argv[i]<<endl;
	    }	
	  }
	}
	else{
	  cerr<<"Erreur de parsage dans la valeur associé à la capacité minimale, valeur reçue : "<<argv[i]<<endl;
	  exit(0);
	}
      }
      break;
    }
    case(7):{//nmin
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if( (code == 12) || (code == 13)){
	  *minN = atoi(argv[i]);
	}
	else{
	  cerr<<"Erreur de parsage dans la valeur du nombre de sommets minimum, valeur reçue : "<<argv[i]<<endl;
	}
      }
      break;
    }
    case(8):{//nolimit
      *nolimit = true;
      break;
    }
    case(9):{//nbexe
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if( (code == 12) || (code == 13)){
	  *nbexe = atoi(argv[i]);
	}
	else{
	  cerr<<"Erreur de parsage dans la valeur du nombre d'exécution par sommet, valeur reçue : "<<argv[i]<<endl;
	}
      }
      break;
    }
    case(10):{//pas
      ++i;
      if(i <argc){
	code = codeArg(toLowerCase(argv[i]));
	if( (code == 12) || (code == 13)){
	  *pas = atoi(argv[i]);
	}
	else{
	  cerr<<"Erreur de parsage dans la valeur du pas d'exécution, valeur reçue : "<<argv[i]<<endl;
	}
      }
      break;
    }
    case(11):{ //0 seul
      cerr<<"Erreur de parsage dans la valeur du nombre d'exécution globale, valeur reçue : "<<argv[i]<<endl;
      break;
    }
    case(12):{//valeur numérique seule
      n = atoi(argv[i]);
      for(int i = 0; i < NBR_ALGO; ++i){
	flags[i] = true;
	summit_nbrs[i] = n;
      }      
      break;
    }
    case(13):{//help
      cout<<usage(argv[0])<<endl;
      exit(13);
    }
    case(14):{//forcelist
      code = codeArg(toLowerCase(argv[i]));
      *forcelist = true;
      break;
    }
    }
    ++i;
  }
  if(*nolimit){//Si on est en mode no-limit et qu'aucun algo n'a été spécifié alors on 
    bool noflag =false;
    int j = 0;
    while(!noflag && (j < NBR_ALGO)){
      noflag = flags[j];
      ++j;
    }
    if(!noflag){ //aucun algo n'a été demandé : on exe tous les algos
      j = 0;
      while(j < NBR_ALGO){
	flags[j] = true;
	++j;
      }
    }
  }
}

double execute(int choiceAlgo, GraphFlow** graphEcart, int k){

  struct timespec t1, t2;
  double ex_t = 0;

  switch(choiceAlgo){
  case 0 : { //Edmonds-Karp
    for (int i=0; i<k; i++) {
      clock_gettime(CLOCK_REALTIME,&t1);
      graphEcart[i]->doEdmondsKarp();
      clock_gettime(CLOCK_REALTIME,&t2);
      t2.tv_sec-=t1.tv_sec;
      t2.tv_nsec-=t1.tv_nsec;
      ex_t+=t2.tv_sec*1000+(t2.tv_nsec/1.0e6);
    }
    break;
  }
  case 1 : { //Dinic
    for (int i=0; i<k; i++) {
      clock_gettime(CLOCK_REALTIME,&t1);
      graphEcart[i]->doDinic();
      clock_gettime(CLOCK_REALTIME,&t2);
      t2.tv_sec-=t1.tv_sec;
      t2.tv_nsec-=t1.tv_nsec;
      ex_t+=t2.tv_sec*1000+(t2.tv_nsec/1.0e6);
    }
    break;
  }
  case 2 : { //Ford-Fulkerson
    for (int i=0; i<k; i++) {
      clock_gettime(CLOCK_REALTIME,&t1);
      graphEcart[i]->doFordFulkerson();
      clock_gettime(CLOCK_REALTIME,&t2);
      t2.tv_sec-=t1.tv_sec;
      t2.tv_nsec-=t1.tv_nsec;
      ex_t+=t2.tv_sec*1000+(t2.tv_nsec/1.0e6);
    }
    break;
  }
  case 3 : { //capacity-scaling
    for (int i=0; i<k; i++) {
      clock_gettime(CLOCK_REALTIME,&t1);
      graphEcart[i]->doCapacityScaling();
      clock_gettime(CLOCK_REALTIME,&t2);
      t2.tv_sec-=t1.tv_sec;
      t2.tv_nsec-=t1.tv_nsec;
      ex_t+=t2.tv_sec*1000+(t2.tv_nsec/1.0e6);
    }
    break;
  }
  }
  return (ex_t/k);
}
  
int main(int argc, char * argv[], char * envp[])
{
  string s;
  if(argc < 2){
    int i= strlen(argv[0])-1;
    while ((i>=0) && (argv[0][i]!='/')) i--;
    i++;
    char * name = new char[(strlen(argv[0])+1-i)];
    strcpy(name,&argv[0][i]);
    name[strlen(name)]='\0';
    s  = usage(name);
    cerr<<s<<endl;
    delete [] name;
  }
  else{
    summit_t* summit_nbrs = new summit_t[NBR_ALGO];
    bool* flags = new bool[NBR_ALGO];
    for(int i = 0; i < NBR_ALGO; ++i){
      summit_nbrs[i] = 0;
      flags[i] = false;
    }
    int nbr_exec = NBR_EXEC_DEF;
    int capMin = CAPMIN_DEF;
    int capMax = CAPMAX_DEF;
    int minN = MINN_DEF;
    int pas = PAS_DEF;
    bool noLimit = NOLIMIT_DEF;
    bool forcelist = FORCE_LIST_DEF;
    parseArguments(argv, flags, summit_nbrs, argc, &nbr_exec, &capMin, &capMax, &minN, &pas, &noLimit, &forcelist); //En cas d'erreur ou de --help, appel la méthode usage
    if(capMin > capMax){
      cerr<<"Erreur : Capacité Minimale > Capacité Maximale"<<endl;
      exit(1);
    }
    summit_t max_summit = minN; //Stock la valeur max du nombre d'arêtes, initialisé au nombre min (2 par déf)
    for(int i = 0; i < NBR_ALGO; ++i){
      if(summit_nbrs[i] > max_summit){
	max_summit = summit_nbrs[i];
      }
    }
    if(noLimit){//en mode noLimit, le max de sommet = min sommet +1, et à chaque tour de boucle, on incrémente le max du pas
      max_summit = minN+1;
      for(int i = 0; i < NBR_ALGO;++i){
	summit_nbrs[i] = max_summit;
      }
    }
    //Creation des fichiers (1 par densité) : densite0.dat, densite1.dat, densite2.dat, densite3.dat, densite4.dat
    ofstream f_d0("outputs/densite0.dat", ios::out | ios::trunc);
    ofstream f_d1("outputs/densite1.dat", ios::out | ios::trunc);
    ofstream f_d2("outputs/densite2.dat", ios::out | ios::trunc);
    ofstream f_d3("outputs/densite3.dat", ios::out | ios::trunc);
    ofstream f_d4("outputs/densite4.dat", ios::out | ios::trunc);
    edges_t * m = new edges_t [5];
    edges_t max;
    GraphFlow ** graphBase;
    GraphFlow ** graphEcart;

    if(f_d0 && f_d1 && f_d2 && f_d3 && f_d4){
      //Ecriture de l'en-tête des fichiers en fonction des algo à appeler
      //En-tête commun
      f_d0 << "#1ere colonne : nombre de sommets\n";
      f_d2 << "#1ere colonne : nombre de sommets\n";
      f_d3 << "#1ere colonne : nombre de sommets\n";
      f_d4 << "#1ere colonne : nombre de sommets\n"; 
      f_d0 << "#2e colonne : temps d'exécution de Edmonds-Karp (en ms)\n";
      f_d1 << "#2e colonne : temps d'exécution de Edmonds-Karp (en ms)\n";
      f_d2 << "#2e colonne : temps d'exécution de Edmonds-Karp (en ms)\n";
      f_d3 << "#2e colonne : temps d'exécution de Edmonds-Karp (en ms)\n";
      f_d4 << "#2e colonne : temps d'exécution de Edmonds-Karp (en ms)\n";
      f_d0 << "#3e colonne : temps d'exécution de Dinic (en ms)\n";
      f_d1 << "#3e colonne : temps d'exécution de Dinic (en ms)\n";
      f_d2 << "#3e colonne : temps d'exécution de Dinic (en ms)\n";
      f_d3 << "#3e  colonne : temps d'exécution de Dinic (en ms)\n";
      f_d4 << "#3e  colonne : temps d'exécution de Dinic (en ms)\n";
      f_d0 << "#4e  colonne : temps d'exécution de Ford-Fulkerson (en ms)\n";
      f_d1 << "#4e  colonne : temps d'exécution de Ford-Fulkerson (en ms)\n";
      f_d2 << "#4e  colonne : temps d'exécution de Ford-Fulkerson (en ms)\n";
      f_d3 << "#4e  colonne : temps d'exécution de Ford-Fulkerson (en ms)\n";
      f_d4 << "#4e  colonne : temps d'exécution de Ford-Fulkerson (en ms)\n";
      f_d0 << "#5e  colonne : temps d'exécution de Capacity-scaling (en ms)\n";
      f_d1 << "#5e  colonne : temps d'exécution de Capacity-scaling (en ms)\n";
      f_d2 << "#5e  colonne : temps d'exécution de Capacity-scaling (en ms)\n";
      f_d3 << "#5e  colonne : temps d'exécution de Capacity-scaling (en ms)\n";
      f_d4 << "#5e  colonne : temps d'exécution de Capacity-scaling (en ms)\n";

      //On fait varier le nombre de sommet de minN (2 par def) à Max(n)
      summit_t j = minN;
      while(j <= max_summit){
	if (j>minN) {
	  j=j-(j%10);
	}
	if(noLimit){
	  max_summit += pas;
	  for(int i = 0; i < NBR_ALGO;++i){
	    summit_nbrs[i] = max_summit;
	  }
	}
	max = (j*(j-1))/2;
	m[0] = j-1;
	m[1] = 0.25*max;
	if (m[1]<(edges_t)j-1)
	  m[1]= j-1;
	m[2]=0.5*max;
	if (m[2]<(edges_t)j-1)
	  m[2]= j-1;
	m[3]=0.75*max;
	if (m[3]<(edges_t)j-1)
	  m[3]= j-1;
	m[4]=max;
	if (m[4]<(edges_t)j-1)
	  m[4]= j-1;
			
	f_d0 <<endl<<j;
	f_d1 <<endl<<j;
	f_d2 <<endl<<j;
	f_d3 <<endl<<j;
	f_d4 <<endl<<j;
	cout<<"Tests pour n = "<<j<<", capMin = "<<capMin<<", capMax = "<<capMax<<", nolimit = "<<noLimit<<", nbr_exec = "<<nbr_exec<<", minN = "<<minN<<" et pas = "<<pas<<endl;
	for(int p = 0; p < 5; ++p)
	  { //Pour chaque densité
	    graphBase = new GraphFlow * [nbr_exec];
	    graphEcart = new GraphFlow * [nbr_exec];
	    for (int k=0; k<nbr_exec; k++)
	      {
		if(forcelist){
		  graphBase[k] = new GraphFlowList(j, m[p]);
		}
		else{
		  graphBase[k] = new GraphFlowMatrix(j,m[p]);
		}
		graphBase[k]->fill(capMin,capMax);
	      }
	    for(int i = 0; i < NBR_ALGO; ++i){	  //Pour chaque algo
	      for (int k=0; k<nbr_exec; k++)  {
		if(forcelist){
		  graphEcart[k] = new GraphFlowList(*graphBase[k]);
		}
		else{
		  graphEcart[k] = new GraphFlowMatrix(*graphBase[k]);
		}
	      }
	      switch(p){ //EN fonction de la densité, on écrit dans un fichier différent
	      case 0 : {
		if ((not flags[i]) || (summit_nbrs[i] < j)) {
		  f_d0 << " -1";
		}
		else {
		  f_d0 << " "<< execute(i, graphEcart, nbr_exec);//On effectue le test pour les bonnes valeurs de 'n' et pour chaque palier de densité
		}
		break;
	      }
	      case 1 : {
		if ((not flags[i]) || (summit_nbrs[i] < j)) {
		  f_d1 << " -1";
		}
		else {
		  f_d1 << " "<<execute(i, graphEcart, nbr_exec);
		}
		break;
	      }
	      case 2 : {
		if ((not flags[i]) || (summit_nbrs[i] < j)) {
		  f_d2 << " -1";
		}
		else {
		  f_d2 << " "<< execute(i, graphEcart, nbr_exec);
		}
		break;
	      }
	      case 3 : {
		if ((not flags[i]) || (summit_nbrs[i] < j)) {
		  f_d3 << " -1";
		}
		else {
		  f_d3 << " "<<execute(i, graphEcart, nbr_exec);
		}
		break;
	      }
	      case 4 : {
		if ((not flags[i]) || (summit_nbrs[i] < j)) {
		  f_d4 << " -1";
		}
		else {
		  f_d4 << " "<<execute(i, graphEcart, nbr_exec);
		}
		break;
	      }
	      }
	      for (int i=0; i<nbr_exec; i++) {
		delete graphEcart[i];
	      }
	    }
	    for (int i=0; i<nbr_exec; i++) {
	      delete graphBase[i];
	    }
	    delete [] graphBase;
	    delete [] graphEcart;

	  }
	j += pas;
      }
    }
    f_d0.close();
    f_d1.close();
    f_d2.close();
    f_d3.close();
    f_d4.close();

    delete [] m;
    delete [] summit_nbrs;
    delete [] flags;    
  }  
  return EXIT_SUCCESS;
}

